﻿using System;
using System.Windows.Input;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using DDU.DataModel;
using DDU.Library;
using System.Windows;
using System.Net;
using System.IO.IsolatedStorage;
using System.Text;
using System.IO;
using System.Xml.Linq;

namespace DDU.ViewModel
{
    public class VacationsViewModel : MainViewModel
    {
        #region Constructor
        WebClient client = new WebClient();

        private string FileName
        {
            get
            { 
                return string.Format("{0}\\{1}_{2}.xml", ConstKeys.VacationDirectoryName, DateTime.Now.Year, GlobalSettings.Language);
            }
        }

        public VacationsViewModel()
        {
            client.DownloadStringCompleted -= DownloadFileCompleted;
            client.DownloadStringCompleted += DownloadFileCompleted;

            if (IsDesignMode)
            {
                return;
            }

            if (!CheckFile())
            {
                client.DownloadStringAsync(new Uri(ConstKeys.VacationUrl + DateTime.Now.Year + "_" + GlobalSettings.Language + ".xml", UriKind.RelativeOrAbsolute));
                IsBusy = client.IsBusy;
            }
            else
            {
                GetXmlDatas();
            }
        } 
        #endregion

        #region Properties
        /// <summary>
        /// Get the customized vacations from database.
        /// </summary>
        public ObservableCollection<VacationInfo> ItemsOfVacations
        {
            get
            {
                if (GlobalSettings.ShowAllVacations)
                {
                    return new ObservableCollection<VacationInfo>(Database.CollectionOfVacations);
                }
                DateTime year = new DateTime(DateTime.Now.Year, 1, 1);
                return new ObservableCollection<VacationInfo>(Database.CollectionOfVacations.Where(a => a.StartTime > year));
            }
        }

        private ObservableCollection<StatutoryVacationInfo> itemsOfStatutotyVacations;
        /// <summary>
        /// Get or set the items of Statutory vacations and display on UI.
        /// </summary>
        public ObservableCollection<StatutoryVacationInfo> ItemsOfStatutotyVacations
        {
            get { return itemsOfStatutotyVacations; }
            set
            {
                itemsOfStatutotyVacations = value;
                RaisePropertyChanged(() => ItemsOfStatutotyVacations);
            }
        }

        private ObservableCollection<FestivalInfo> itemsOfFestivals;
        /// <summary>
        /// Get or set the items of festivals and display on UI.
        /// </summary>
        public ObservableCollection<FestivalInfo> ItemsOfFestivals
        {
            get { return itemsOfFestivals; }
            set
            {
                itemsOfFestivals = value;
                RaisePropertyChanged(() => ItemsOfFestivals);
            }
        }

        private VacationInfo selectedVacation;
        /// <summary>
        /// Get or set the selected customize vacation.
        /// </summary>
        public VacationInfo SelectedVacation
        {
            get { return selectedVacation; }
            set
            {
                selectedVacation = value;
                RaisePropertyChanged(() => SelectedVacation);
                RaisePropertyChanged(() => DeleteCommand);
            }
        }

        private bool isBusy = false;
        /// <summary>
        /// Get or set weather the webclient is busying downloading vacations file.
        /// </summary>
        public bool IsBusy
        {
            get { return isBusy; }
            set
            {
                isBusy = value;
                RaisePropertyChanged(() => IsBusy);
                RaisePropertyChanged(() => RefreshCommand);
            }
        }
        #endregion

        #region Method
        private void Remove(VacationInfo entity)
        {
            Database.CollectionOfVacations.DeleteOnSubmit(entity);
            Submit();
            SelectedVacation = null;
            RaisePropertyChanged(() => SelectedVacation);
            RaisePropertyChanged(() => DeleteCommand);
            RaisePropertyChanged(() => ItemsOfVacations);
        }

        private bool CheckFile()
        {
            using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
            {
                return store.FileExists(FileName);
            }
        }

        private void GetXmlDatas()
        {
            using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
            {
                
                IsolatedStorageFileStream stream = store.OpenFile(FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
                XDocument xdoc = XDocument.Load(stream);

                XElement vacations = xdoc.Descendants("vacations").First();

                IEnumerable<StatutoryVacationInfo> vicationItems = (from item in vacations.Descendants("item")
                                                            select new StatutoryVacationInfo()
                                                            {
                                                                Title = item.Element("title").Value,
                                                                Start = DateTime.Parse(item.Element("start").Value),
                                                                End = DateTime.Parse(item.Element("end").Value),
                                                                Duration = Convert.ToInt32(item.Element("duration").Value)
                                                            });

                ItemsOfStatutotyVacations = new ObservableCollection<StatutoryVacationInfo>(vicationItems);
                RaisePropertyChanged(() => ItemsOfStatutotyVacations);

                XElement festivals = xdoc.Descendants("festivals").First();

                IEnumerable<FestivalInfo> festivalItems = (from item in festivals.Descendants("item")
                                                           select new FestivalInfo()
                                                            {
                                                                Title = item.Element("title").Value,
                                                                Date = DateTime.Parse(item.Element("date").Value),
                                                                Type = item.Element("type").Value
                                                            });

                ItemsOfFestivals = new ObservableCollection<FestivalInfo>(festivalItems);
                RaisePropertyChanged(() => ItemsOfFestivals);

                stream.Close();
                stream.Dispose();
                IsBusy = client.IsBusy;
            }
        }
        
        private void DownloadFileCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                byte[] buffer = Encoding.UTF8.GetBytes(e.Result);
                Stream stream = new MemoryStream(buffer);
                RecordData(stream.Length);
                using (BinaryReader reader = new BinaryReader(stream))
                {
                    using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
                    {
                        if (store.FileExists(FileName))
                        {
                            store.DeleteFile(FileName);
                        }

                        using (IsolatedStorageFileStream fileStream = store.OpenFile(FileName, FileMode.OpenOrCreate, FileAccess.Write))
                        {
                            using (BinaryWriter writer = new BinaryWriter(fileStream))
                            {
                                writer.Write(reader.ReadBytes(Convert.ToInt32(stream.Length)));
                            }
                            fileStream.Close();
                            fileStream.Dispose();
                        }
                    }
                }
                GetXmlDatas();
            }
        }
        #endregion

        #region Commands
        public ICommand DeleteCommand
        {
            get
            {
                return new GenericCommand()
                {
                    CanExecuteCallback = delegate { return SelectedVacation != null; },
                    ExecuteCallback = delegate
                    {
                        if (MessageBox.Show("确定要删除吗？", "删除提醒", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
                        {
                            Remove(SelectedVacation);
                        }
                    }
                };
            }
        }

        public ICommand RefreshCommand
        {
            get
            {
                return new GenericCommand()
                {
                    CanExecuteCallback = delegate { return !IsBusy; },
                    ExecuteCallback = delegate
                    {
                        client.DownloadStringAsync(new Uri(ConstKeys.VacationUrl + DateTime.Now.Year + "_" + GlobalSettings.Language + ".xml", UriKind.RelativeOrAbsolute));
                        IsBusy = client.IsBusy;
                    }
                };
            }
        } 
        #endregion
    }
}
